﻿using System;
using CoreTypes;
using System.Linq;
using System.Custom;
using System.Drawing;
using CustomControls;
using HtmlViewControl;
using System.Custom.Web;
using System.Collections;
using System.Custom.Window;
using System.Windows.Forms;
using System.ComponentModel;
using MainModule.Properties;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace MainModule
{
   public partial class MediaWindow : Window, IMediaWindow
   {
      #region Data

      Font FButtonFont;
      Font FButtonFontB;
      bool FIsResizing;
      int FInputCaretPos;
      bool FSessionTypeMultiSelect;
      int FButtonSelectSessionWidth = 132;
      Size FDefaultSize = new Size(680, 740);
      StringFormat FButtonStringFormat = new StringFormat(StringFormatFlags.NoWrap);

      HtmlView FLogToolbar;
      MediaSessionSet FMediaSessions;
      IMediaSession FExclusiveSession;
      IMediaSession FMulticastSession;
      ContextMenuStrip FLastShownMenu;
      IMediaSession FActiveMediaSession;
      InternetCommunicator FCommunicator;
      List<IMediaSession> FHiddenSessions;
      SessionVisualizer FStartPageVisualizer;
      Collection<ChatMessage> FDraftMessages;

      Image FExclamationImage = ResourceWrapper.Warning;
      Image FButtonImageEmpty = ResourceWrapper.EmptyBitmap;
      Image FSplitterImage = ResourceWrapper.GetImage("SplitterGrip");
      Image FSessionButtonImage = ResourceWrapper.SayingBubbleBlue;
      Image FSessionButtonImageFlashed = ResourceWrapper.SayingBubble;
      Image FSessionMenuImage = ResourceWrapper.GetImage("Chat2_18");
      Image FContactMenuImage = ResourceWrapper.GetImage("Info_S_18");
      Image FFindMenuImage = ResourceWrapper.GetImage("FindHS");//("Magnifier_S_H18");
      Image FHistoryMenuImage = ResourceWrapper.GetImage("HistoryFolder_S_18");
      Image FDropDownArrowImage1 = ResourceWrapper.GetImage("DropDownArrow");
      Image FDropDownArrowImage2 = ResourceWrapper.GetImage("DropDownArrow2");

      #endregion

      #region Initializers

      private void CreateLogToolbar()
      {
         FLogToolbar = new HtmlView();
         FLogToolbar.Dock = DockStyle.Bottom;
         panelLogToolbar.Controls.Add(FLogToolbar);
         FLogToolbar.HtmlControlEvent += logToolbar_HtmlControlEvent;
         FLogToolbar.HtmlControlKeyPress += logToolbar_HtmlControlKeyPress;

         CssReader css = new CssReader(Resources.LogToolbarStyle);
         string height = css["body", "height"];
         string padding = css["body", "padding"];
         if (height != null && padding != null)
         {
            string[] paddings = padding.ToString().Split(' ');
            if (paddings.Length > 2)
            {
               panelLogToolbar.MaximumSize = new Size(0, int.Parse(height.SubstrBefore("px")) + 
                                                         int.Parse(paddings[0].SubstrBefore("px")) +
                                                         int.Parse(paddings[2].SubstrBefore("px")));
            }
            else
            {
               panelLogToolbar.MaximumSize = new Size(0, int.Parse(height.SubstrBefore("px")) + 
                                                         int.Parse(paddings[0].SubstrBefore("px")) * 2);
            }
         }
         FLogToolbar.Height = panelLogToolbar.MaximumSize.Height;
         FLogToolbar.LoadHtml(Resources.LogToolbar.Replace("<style />", "<style>" + Resources.LogToolbarStyle + "</style>"), "");
      }
      public MediaWindow(IMediaSession session)
      {
         InitializeComponent();

         FCommunicator = InternetCommunicator.Self;

         FExclusiveSession = session;
         FMediaSessions = new MediaSessionSet(false);
         FHiddenSessions = new List<IMediaSession>();
         FDraftMessages = new Collection<ChatMessage>();

         FButtonFont = new Font(toolStripMiddle.Font, FontStyle.Regular);
         FButtonFontB = new Font(toolStripMiddle.Font, FontStyle.Bold);

         panelLogToolbar.Height = 0;
         FSessionTypeMultiSelect = false;
         panelSplitter.Visible = Settings.Default.ShowInputResizeBar;
         FButtonStringFormat.Trimming = StringTrimming.EllipsisCharacter;
         textBoxInput.Font = new Font(Settings.Default.InputFont, Settings.Default.InputFontSize);

         SessionSelect += window_SessionSelect;
         Settings.Default.PropertyChanged += settings_PropertyChanged;
         FCommunicator.MessageAccepted += communicator_MessageAccepted;
         FCommunicator.PropertyChanged += communicator_PropertyChanged;
         FCommunicator.RequestUserInfoState += OnRequestUserInfoState;
         FCommunicator.CurrentAccountChanged += communicator_CurrentAccountChanged;
         FCommunicator.EmoticonPopup.EmoSelected += emoticonMenu_EmoSelected;

         menuItemSession.DropDown = InternetCommunicator.Self.Components.menuChatSession;
         menuItemHistory.DropDown = InternetCommunicator.Self.Components.menuHistory;
         menuItemFind.DropDown = InternetCommunicator.Self.Components.menuTextSearch;
         menuItemContact.DropDown = InternetCommunicator.Self.Components.menuContact;

         //FMulticastSession = FCommunicator.CreateMediaSession(FCommunicator.SupportedMediaSessionTypes[typeof(ChatSession)],
         //                    FCommunicator.CurrentAccount, null, SessionVisibility.Private, SessionHostingType.None, null, SessionSubtype.Translation);
         //FMulticastSession.Subject = Resources.S_Message_distribution;
         //FMulticastSession.LogEvents = true;
         //AttachSession(FMulticastSession);

         //CreateStartPageVisualizer(typeof(ChatControl), typeof(ChatSession));

         ColorTheme = FCommunicator.ColorTheme;
         RenderMode = FCommunicator.RenderMode;

         panelSplitter.MouseDown += delegate(object sender, MouseEventArgs e)
         {
            FIsResizing = true;
         };
         panelSplitter.MouseUp += delegate(object sender, MouseEventArgs e)
         {
            FIsResizing = false;
         };
         panelSplitter.MouseMove += delegate(object sender, MouseEventArgs e)
         {
            if (FIsResizing)
            {
               Settings.Default.InputHeight =
               panelInputLayout.Height =
                        Height - PointToClient(Cursor.Position).Y -
                        (toolStripMiddle.Height + panelBottomToolbar.Height + statusBar.Height + panelSplitter.Height);

               toolStripMiddle.Refresh();
            }
         };

         if (ExclusiveSessionMode) ActiveMediaSession = FExclusiveSession;

         Icon = Icon.FromHandle(ResourceWrapper.GetImage("OdnoklPostBlue").GetHicon());
      }
      protected override void Dispose(bool disposing)
      {
         Settings.Default.PropertyChanged -= settings_PropertyChanged;
         FCommunicator.MessageAccepted -= communicator_MessageAccepted;
         FCommunicator.PropertyChanged -= communicator_PropertyChanged;
         FCommunicator.RequestUserInfoState -= OnRequestUserInfoState;
         FCommunicator.CurrentAccountChanged -= communicator_CurrentAccountChanged;
         FCommunicator.EmoticonPopup.EmoSelected -= emoticonMenu_EmoSelected;

         if (disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }
      protected override void OnFileDialogVisibleChanged(object sender, EventArgs e)
      {
         if (Shell.FileDialogVisible)
         {
            FInteractiveState = Visible;
            if (Visible) Hide();
         }
         else
         {
            Visible = FInteractiveState;
         }
      }

      #endregion

      #region IVisualRegion

      public override ColorTheme ColorTheme
      {
         get
         {
            return base.ColorTheme;
         }
         set
         {
            base.ColorTheme = value;
            Refresh();
         }
      }
      public override ToolStripRenderMode RenderMode
      {
         get
         {
            return base.RenderMode;
         }
         set
         {
            if (RenderMode == value) return;

            base.RenderMode = value;

            menuMedia.RenderMode = value;
            statusBar.RenderMode = value;
            toolStripBottom.RenderMode = value;
            toolStripMiddle.RenderMode = value;

            menuView.RenderMode = value;
            menuSelectSession.RenderMode = value;

            AdjustControlsGeometry();
         }
      }

      #endregion

      #region MediaWindow

      private bool MulticastMode
      {
         get
         {
            return itemMulticastMode.Checked;
         }
         set
         {
            itemMulticastMode.Checked = value;
         }
      }
      private ChatSession ActiveChatSession
      {
         get
         {
            return FActiveMediaSession as ChatSession;
         }
         set
         {
            FActiveMediaSession = value;
         }
      }
      private IMediaSession MulticastSession
      {
         get
         {
            return FMulticastSession;
         }
      }
      private event SessionSelectHandler SessionSelect;
      private event SessionTypeSelectHandler SessionTypeSelect;

      private void DoPost()
      {
         ChatSession session = ActiveChatSession;

         if (textBoxInput.Text.Trim() != "" && session != null)
         {
            ChatMessage message = new ChatMessage(textBoxInput.Text, session);

            if (session == MulticastSession) message.Gsid = null;

            session.SendChatMessage(message);
         }
         else System.Media.SystemSounds.Beep.Play();

         if (session.ChatControl.HistoryPageIndex > 0 &&
             session.ChatControl.HistoryFilesCount != session.ChatControl.HistoryPageIndex + 1) session.ChatControl.ShowHistoryPage(-1, false, true);

         textBoxInput.Focus();
      }
      private void SelectAllSessions()
      {
         foreach (IMediaSession session in FMediaSessions) SelectSession(session);
      }
      private void DeselectAllSessions()
      {
         ActiveMediaSession = null;
      }
      private void UpdateMediaToolbar()
      {
         IEnumerable<ToolStripLabel> allLabels = ((IEnumerable)menuMedia.Items).OfType<ToolStripLabel>().Where(l =>
                     l.Tag is IMediaSession || l.Tag is User);

         foreach (ToolStripLabel label in allLabels) label.Visible = false;

         if (ActiveMediaSession != null)
         {
            IEnumerable<ToolStripLabel> sessionLabels = allLabels.Where(l => ActiveMediaSession.IsPersonal ?
                        l.Tag == ActiveMediaSession : ActiveMediaSession.IsParticipant(l.Tag as User));

            foreach (ToolStripLabel label in sessionLabels) label.Visible = true;
         }
      }
      private void InsertEmo(string emo)
      {
         int pos = FInputCaretPos;
         emo = textBoxInput.Text.Length == 0 ? emo : " " + emo + " ";
         textBoxInput.Text = textBoxInput.Text.Insert(pos, emo).Replace("  ", " ").Trim();
         textBoxInput.SelectionStart = pos + emo.Length;
         textBoxInput.SelectionLength = 0;
      }
      private void PrepareWindowForChat()
      {
         textBoxInput.Focus();
         foreach (ChatSession session in FMediaSessions.Where(s => s is ChatSession).Select(s => s as ChatSession))
         {
            session.ChatControl.Dock = DockStyle.None; // bug in HTMLayout with hiding its content
            session.ChatControl.Dock = DockStyle.Fill;
            session.ChatControl.ScrollToEnd(false);
            session.ChatControl.RefreshView();
         }
      }
      private void AdjustToolbarButtons()
      {
         int height = Settings.Default.ShowMediaWindowMenuBarIcons ? 28 : (Settings.Default.ShowMediaWindowTopToolbar ? 23 : 24);

         menuMedia.Parent.MaximumSize = new Size(0, height);
         if (Settings.Default.ShowMediaWindowMenuBar) menuMedia.Height = menuMedia.Parent.Height = height;

         int heightPadding = RenderMode == ToolStripRenderMode.System && Computer.OSPlatform == OS.VistaOrLater && IsThemeActive ? 3 : 5;

         if (Settings.Default.ShowMediaWindowMenuBarIcons && !Settings.Default.ShowMediaWindowMenuBarText)
         {
            menuItemSession.AutoSize = false;
            menuItemSession.Width = 33;
            menuItemSession.Margin = new Padding(0, 0, 5, 0);
            menuItemSession.Padding = new Padding(0, 0, 0, 0);
            menuItemSession.Height = menuMedia.Height - heightPadding;
            menuItemSession.DisplayStyle = ToolStripItemDisplayStyle.None;

            menuItemHistory.AutoSize = false;
            menuItemHistory.Width = menuItemSession.Width;
            menuItemHistory.Margin = menuItemSession.Margin;
            menuItemHistory.Padding = menuItemSession.Padding;
            menuItemHistory.Height = menuItemSession.Height;
            menuItemHistory.DisplayStyle = menuItemSession.DisplayStyle;

            menuItemFind.AutoSize = false;
            menuItemFind.Width = menuItemSession.Width;
            menuItemFind.Margin = menuItemSession.Margin;
            menuItemFind.Padding = menuItemSession.Padding;
            menuItemFind.Height = menuItemSession.Height;
            menuItemFind.DisplayStyle = menuItemSession.DisplayStyle;

            menuItemContact.AutoSize = false;
            menuItemContact.Width = menuItemSession.Width;
            menuItemContact.Margin = menuItemSession.Margin;
            menuItemContact.Padding = menuItemSession.Padding;
            menuItemContact.Height = menuItemSession.Height;
            menuItemContact.DisplayStyle = menuItemSession.DisplayStyle;
         }
         else
         {
            menuItemSession.AutoSize = true;
            menuItemSession.Margin = new Padding(0, 0, 1, 0);
            menuItemSession.Padding = new Padding(2, 0, 2, 0);
            menuItemSession.DisplayStyle = Settings.Default.ShowMediaWindowMenuBarIcons &&
                                           Settings.Default.ShowMediaWindowMenuBarText ?
                                           ToolStripItemDisplayStyle.ImageAndText : ToolStripItemDisplayStyle.Text;

            menuItemHistory.AutoSize = true;
            menuItemHistory.Margin = menuItemSession.Margin;
            menuItemHistory.Padding = menuItemSession.Padding;
            menuItemHistory.DisplayStyle = menuItemSession.DisplayStyle;

            menuItemFind.AutoSize = true;
            menuItemFind.Margin = menuItemSession.Margin;
            menuItemFind.Padding = menuItemSession.Padding;
            menuItemFind.DisplayStyle = menuItemSession.DisplayStyle;

            menuItemContact.AutoSize = true;
            menuItemContact.Margin = menuItemSession.Margin;
            menuItemContact.Padding = menuItemSession.Padding;
            menuItemContact.DisplayStyle = menuItemSession.DisplayStyle;
         }

         //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;

         buttonSelectSession.AutoSize = false;
         buttonSelectSession.Width = 33;
         buttonSelectSession.Margin = new Padding(0, 0, 0, 0);
         buttonSelectSession.Padding = menuItemSession.Padding;
         buttonSelectSession.ShowDropDownArrow = false;
         buttonSelectSession.DisplayStyle = ToolStripItemDisplayStyle.None;
         buttonSelectSession.Height = toolStripMiddle.Height - (heightPadding +
                                      (RenderMode == ToolStripRenderMode.System && !IsThemeActive ? 0 : 1));

         buttonClearText.AutoSize = false;
         buttonClearText.Height = toolStripBottom.Height - heightPadding;

         buttonEmoticons.AutoSize = false;
         buttonEmoticons.Height = buttonClearText.Height;

         buttonSend.AutoSize = false;
         buttonSend.Height = buttonClearText.Height;
      }
      private void ArrangeSessionButtons()
      {
         int i = 0;
         int width = FButtonSelectSessionWidth;
         int toolWidth = Settings.Default.MediaWindowRect.Width - buttonSelectSession.Width;
         int count = toolWidth / width;

         foreach (ToolStripItem button in toolStripMiddle.Items)
         {
            IMediaSession session = button.Tag as IMediaSession;
            if (session != null)
            {
               button.Width = width;
               button.Height = buttonSelectSession.Height;
               button.Visible = ++i <= count && !FHiddenSessions.Contains(session);
            }
         }
      }
      private void AdjustControlsGeometry()
      {
         menuMedia.AutoSize = false;
         toolStripBottom.AutoSize = false;

         menuMedia.Height = menuMedia.Parent.MaximumSize.Height;
         toolStripBottom.Height = toolStripBottom.Parent.MaximumSize.Height;

         int leftPadding = IsThemeActive || WindowState == FormWindowState.Maximized ? 2 : 1;
         Padding padding = new Padding(leftPadding, 0, 2, 0);

         toolStripMiddle.Padding = padding;
         toolStripBottom.Padding = padding;
         tableLayoutTextBox.Padding = padding;

         //int topPadding = RenderMode == ToolStripRenderMode.System ?
         //   (Settings.Default.ShowMediaWindowMenuBar || Settings.Default.ShowMediaWindowTopToolbar ? 0 : 2) : 2;

         int topPadding = Settings.Default.ShowMediaWindowMenuBar || Settings.Default.ShowMediaWindowTopToolbar ? 0 : 2;

         panelSessionVisualizerBase.Padding = new Padding(leftPadding, topPadding, 2, 0);
         //panelSessionVisualizer.Padding = new Padding(3, 3, 3, 0);

         panelTextBox.BorderStyle = IsThemeActive ? BorderStyle.None : BorderStyle.Fixed3D;
         tableLayoutTextBox.CellBorderStyle = IsThemeActive ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None;

         AdjustToolbarButtons();
         ArrangeSessionButtons();

         Refresh();
      }
      private void DeselectAllSessionButtons()
      {
         foreach (ToolStripItem button in toolStripMiddle.Items)
         {
            if (button.Tag is IMediaSession) ((ToolStripButton)button).Checked = false;
         }
         foreach (ToolStripItem item in menuSelectSession.Items)
         {
            if (item.Tag is IMediaSession) ((ToolStripMenuItem)item).Checked = false;
         }
      }
      private void SetStatusBarText(string text)
      {
         statusBarLabel.Text = text;
      }
      private void SetStatusBarImage(Image image)
      {
         if (statusBarLabel.Tag == null)
         {
            statusBarLabel.DisplayStyle = ToolStripItemDisplayStyle.Text;
            statusBarLabelCloseSession.Image = statusBarLabel.Image = image;
         }
         else
         {
            statusBarLabel.Image = image;
            statusBarLabel.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
         }
      }
      protected override void UpdatewWindowView()
      {
         UpdateMediaToolbar();
         SetStatusBarParams(null, null, null);
         textBoxInput.Enabled = ActiveMediaSession != null;
         Text = ActiveMediaSession != null ? ActiveMediaSession.Caption : Resources.S_Session_not_selected;
      }
      private void ShowSession(IMediaSession session)
      {
         if (ActiveMediaSession == session) return;

         AttachSession(session);
         FHiddenSessions.Remove(session);
         FActiveMediaSession = session;

         session.Activate();

         if (SessionSelect != null) SessionSelect(session, true, session == FMulticastSession || !MulticastMode);
         if (SessionTypeSelect != null) SessionTypeSelect(session.GetType(), true);
      }
      private void HideSession(IMediaSession session)
      {
         if (FActiveMediaSession == session) FActiveMediaSession = null;
         ToolStripButton button = GetSessionSelectButton(session);
         if (button != null) button.Visible = false;
         FHiddenSessions.Add(session);
         session.Hide();

         IMediaSession session2 = FMediaSessions.Except(FHiddenSessions).LastOrDefault(s => s != FMulticastSession);
         if (session2 == null) session2 = FMediaSessions.LastOrDefault(s => s != FMulticastSession);

         ShowSession(session2 != null ? session2 : session);
      }
      private void SelectSession(IMediaSession session)
      {
         if (MulticastMode)
         {
            IncludeSessionToSelection(session);
         }
         else
         {
            ShowSession(session);
         }
      }
      private void DeselectSession(IMediaSession session)
      {
         if (MulticastMode) ExcludeSessionFromSelection(session);
      }
      private void ShowNewSessionVisualizer(Type sessionType)
      {
         Type type = FCommunicator.SupportedMediaSessionTypes[sessionType].VisualizerType;

         if (FStartPageVisualizer == null || FStartPageVisualizer.GetType() != type)
         {
            CreateStartPageVisualizer(type, sessionType);
         }

         ActiveMediaSession = null;
         FStartPageVisualizer.Visualize();
         Text = FStartPageVisualizer.SessionCaption;
      }
      private void PlaceVisualizer(ISessionVisualizer visualizer)
      {
         UserControl visualizerControl = (UserControl)visualizer;
         visualizerControl.Dock = DockStyle.Fill;
         visualizerControl.Margin = new Padding(0);
         panelSessionVisualizer.Controls.Add(visualizerControl);
      }
      private void IncludeSessionToSelection(IMediaSession session)
      {
         if (!CheckGroupMessagesCompatibility(session)) return;

         if (FActiveMediaSession != FMulticastSession)
         {
            FMulticastSession.RemoveAllParticipants();
            ShowSession(FMulticastSession);
         }
         if (!FMulticastSession.AddParticipant(session.Interlocutor, false))
         {
            System.Media.SystemSounds.Beep.Play();
         }

         if (SessionSelect != null) SessionSelect(session, true, false);
      }
      private void ExcludeSessionFromSelection(IMediaSession session)
      {
         if (!CheckGroupMessagesCompatibility(session)) return;

         if (FActiveMediaSession != FMulticastSession)
         {
            ShowSession(FMulticastSession);
         }

         FMulticastSession.RemoveParticipant(session.Interlocutor);

         if (SessionSelect != null) SessionSelect(session, false, false);
      }
      private void HideAllSessionVisualizers(ISessionVisualizer except)
      {
         panelSessionVisualizer.SuspendLayout();
         foreach (UserControl visualizer in panelSessionVisualizer.Controls) visualizer.Visible = (visualizer == except);
         panelSessionVisualizer.ResumeLayout();
      }
      private void CreateStartPageVisualizer(Type type, Type sessionType)
      {
         if (FStartPageVisualizer != null)
         {
            FStartPageVisualizer.Dispose();
            FStartPageVisualizer = null;
         }

         object[] args = { FCommunicator, null };

         FStartPageVisualizer = (SessionVisualizer)Activator.CreateInstance(type, args);

         FStartPageVisualizer.SessionType = sessionType;
         PlaceVisualizer(FStartPageVisualizer);
      }
      private bool CheckGroupMessagesCompatibility(IMediaSession session)
      {
         ToolStripButton button = (ToolStripButton)GetSessionSelectButton(session);

         return (session != FMulticastSession && (button != null && button.Visible) && session is ChatSession && session.IsPersonal);
      }
      private ToolStripMenuItem GetSessionSelectItem(IMediaSession session)
      {
         foreach (ToolStripItem item in menuSelectSession.Items)
         {
            if (item.Tag == session) return item as ToolStripMenuItem;
         }
         return null;
      }
      private ToolStripButton GetSessionSelectButton(IMediaSession session)
      {
         foreach (ToolStripItem button in toolStripMiddle.Items)
         {
            if (button.Tag == session) return (ToolStripButton)button;
         }
         return null;
      }
      private ToolStripButton AddSessionSelectButton(IMediaSession session)
      {
         ToolStripButton button = new ToolStripButton();

         button.Tag = session;
         button.AutoSize = false;
         button.AutoToolTip = true;
         button.DoubleClickEnabled = true;
         button.Margin = new Padding(0, 0, 1, 0);
         button.Padding = new Padding(0, 0, 0, 0);
         button.ToolTipText = session.Caption;
         button.ImageTransparentColor = Color.Magenta;
         button.Alignment = ToolStripItemAlignment.Left;
         button.TextAlign = ContentAlignment.MiddleLeft;
         button.ImageAlign = ContentAlignment.MiddleLeft;
         button.Width = FButtonSelectSessionWidth;
         button.Height = buttonSelectSession.Height;
         button.Overflow = ToolStripItemOverflow.Never;
         button.ImageScaling = ToolStripItemImageScaling.None;
         button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
         button.Paint += new PaintEventHandler(sessionButton_Paint);
         button.MouseDown += new MouseEventHandler(buttonSelectSession_MouseDown);
         button.DoubleClick += new EventHandler(buttonSelectSession_DoubleClick);
         button.LocationChanged += new EventHandler(buttonSelectSession_LocationChanged);

         toolStripMiddle.Items.Insert(0, button);

         return button;
      }
      private void SetStatusBarParams(string text, Image image, object data)
      {
         if (ActiveMediaSession != null)
         {
            if (text == null)
            {
               switch (ActiveMediaSession.State)
               {
                  case SessionState.Sending:
                     {
                        text = Resources.S_Sending_message_to_users.Replace("<users>", ActiveMediaSession.RecipientsNames);
                        break;
                     }
                  case SessionState.Waiting:
                     {
                        text = Resources.S_Waiting_message_acknowledge;
                        break;
                     }
                  case SessionState.Establishing:
                     {
                        if (ActiveMediaSession.Invitees.Count > 0)
                        {
                           text = Resources.S_Establishing_session_with_users.Replace("<users>", StringExt.Join(
                                  ActiveMediaSession.Invitees.Select(user => user.ToString()), ", "));
                        }
                        else
                        {
                           text = SessionState.Ready.ToString();
                        }
                        break;
                     }
                  default:
                     {
                        text = ActiveMediaSession.IsPersonal && ActiveMediaSession.Interlocutor != null ?
                               ActiveMediaSession.Interlocutor.ToString(InfoStrings.NameServiceFullStatus) :
                               text = ActiveMediaSession.State.ToString();
                        break;
                     }
               }
            }

            if (ActiveMediaSession.IsPersonal && ActiveMediaSession.Interlocutor != null && image == null)
            {
               image = Status.GetImage(ActiveMediaSession.Interlocutor.Status.Value);
            }

            SetStatusBarText(text);
            statusBarLabel.Tag = data;
            SetStatusBarImage(image);
         }
         else
         {
            SetStatusBarText("");
            statusBarLabel.Tag = null;
            SetStatusBarImage(null);
         }
      }

      public string SearchString
      {
         get
         {
            return FLogToolbar.GetElementById("inputFind").Value.ToString();
         }
      }
      public void HideTextSearch()
      {
         ControlEffects.Slide(panelLogToolbar, SlideAction.Collapse, false);
         panelSessionVisualizer.Padding = new Padding(1);
         ActiveChatSession.ChatControl.ShowHistoryPage(-1, false, true);
         textBoxInput.Focus();
      }
      public bool TextSearchVisible
      {
         get
         {
            return panelLogToolbar.Height > 1 && FLogToolbar != null;
         }
      }
      public bool ExclusiveSessionMode
      {
         get
         {
            return FExclusiveSession != null;
         }
      }
      public IMediaSession ActiveMediaSession
      {
         get
         {
            return FActiveMediaSession;
         }
         set
         {
            if (FActiveMediaSession == value) return;

            if (value == null)
            {
               FActiveMediaSession = null;
               DeselectAllSessionButtons();
               HideAllSessionVisualizers(null);
               UpdatewWindowView();
            }
            else
            {
               ShowSession(value);
            }
         }
      }
      public void ShowTextSearch(bool filtered)
      {
         if (FLogToolbar == null) CreateLogToolbar();

         ControlEffects.Slide(panelLogToolbar, SlideAction.Expand, false);
         panelSessionVisualizer.Padding = new Padding(1, 0, 1, 1);
         FLogToolbar.SetFocus("inputFind");
         ActiveChatSession.ChatControl.FilteredSearch = filtered;
      }
      public void AttachSession(IMediaSession session)
      {
         IMediaWindow mediaWindow = session.Visualizer == null ? null : session.Visualizer.MediaWindow;

         if (mediaWindow == this) return;

         if (mediaWindow != null) mediaWindow.DetachSession(session);

         FMediaSessions.Add(session);

         session.InitializeMedia();
         PlaceVisualizer(session.Visualizer);

         session.Closed += session_Closed;
         session.Closing += session_Closing;
         session.Activated += session_Activated;
         session.PresenceNotified += OnPresenceNotified;
         session.InvitationReceived += OnInvitationReceived;
         session.SendInvitationState += OnSendInvitationState;
         session.AcknowledgeReceived += OnAcknowledgeReceived;
         session.ChatMessageReceived += OnChatMessageReceived;
         session.SendChatMessageState += OnSendChatMessageState;
         session.ParticipantsChanged += session_ParticipantsChanged;
         session.InvitationReplyReceived += OnInvitationReplyReceived;

         if (session is ChatSession)
         {
            ChatSession chatSession = session as ChatSession;
            chatSession.ChatControl.HistoryPageChanged += chatControl_HistoryPageChanged;
         }

         if (session != FMulticastSession) AddSessionSelectButton(session);
      }
      public void DetachSession(IMediaSession session)
      {
         if (FMediaSessions.Remove(session))
         {
            session.Hide();
            session.Closed -= session_Closed;
            session.Closing -= session_Closing;
            session.Activated -= session_Activated;
            session.PresenceNotified -= OnPresenceNotified;
            session.InvitationReceived -= OnInvitationReceived;
            session.SendInvitationState -= OnSendInvitationState;
            session.AcknowledgeReceived -= OnAcknowledgeReceived;
            session.ChatMessageReceived -= OnChatMessageReceived;
            session.SendChatMessageState -= OnSendChatMessageState;
            session.ParticipantsChanged -= session_ParticipantsChanged;
            session.InvitationReplyReceived -= OnInvitationReplyReceived;

            if (session is ChatSession)
            {
               ChatSession chatSession = session as ChatSession;
               chatSession.ChatControl.HistoryPageChanged -= chatControl_HistoryPageChanged;
            }
            if (ExclusiveSessionMode)
            {
               BeginInvoke(new Action(() => { Dispose(); }));
            }
            else
            {
               if (session == ActiveMediaSession) ActiveMediaSession = null;

               ToolStripMenuItem item = GetSessionSelectItem(session);
               ToolStripButton button = GetSessionSelectButton(session);

               FHiddenSessions.Remove(session);
               menuSelectSession.Items.Remove(item);
               toolStripMiddle.Items.Remove(button);
               panelSessionVisualizer.Controls.Remove(session.Visualizer as UserControl);

               if (item != null) item.Dispose();
               if (button != null) button.Dispose();

               session = FMediaSessions.Except(FHiddenSessions).LastOrDefault(s => s != FMulticastSession);
               if (session == null) session = FMediaSessions.LastOrDefault(s => s != FMulticastSession);

               if (session != null) SelectSession(session); else Close();
            }
         }
      }
      public void ShowAddParticipant(IMediaSession session)
      {
         if (session.IsPersonal)
         {
            DeselectAllSessions();
            ShowNewSessionVisualizer(session.GetType());
            FStartPageVisualizer.ShowSessionParams(session, true);
            Text = session.Caption;
         }
         else
         {
            session.Visualizer.ShowStartPage(false);
         }
      }
      public void ComposeReply(ChatMessage message, string reply)
      {
         textBoxInput.Text = message.Text;

         string[] lines = new string[textBoxInput.Lines.Length];

         textBoxInput.Lines.CopyTo(lines, 0);

         for (int i = 0; i < textBoxInput.Lines.Length; i++)
         {
            lines[i] = textBoxInput.Lines[i].Insert(0, "> ");
         }

         textBoxInput.Lines = lines;

         textBoxInput.Text += "\r\n\r\n- " + reply;

         textBoxInput.SelectionStart = textBoxInput.Text.Length;

         textBoxInput.ScrollToCaret();
      }

      #endregion

      #region ICommunicationEventHanldlerObject

      public void OnSendInvitationState(object sender, MessagingOperationEventArgs e)
      {
         OnSendChatMessageState(sender, e);
      }
      public void OnSendChatMessageState(object sender, MessagingOperationEventArgs e)
      {
         Image statusImage = null;
         String statusText = null;
         Object statusData = null;

         string users = e.EventMessage.MediaSession.RecipientsNames;

         if (e.Error != null)
         {
            statusData = e.Error;
            statusText = e.Error.Reason;
            statusImage = FExclamationImage;
            //statusText = Resources.S_We_have_some_troubles + Resources.S_Troubles_while_sending_your_message.Replace("<user>", users) + Resources.S_Click_here_to_get_more_information;
         }
         else
         {
            if (e.State == OperationState.DataSending)
            {
               textBoxInput.Text = String.Empty;
            }
            else if (e.State == OperationState.DataSent)
            {
               statusText = Resources.S_Last_message_was_sent.Replace("<user>", users).Replace("<time>", DateTime.Now.ToLongTimeString());
            }
         }
         SetStatusBarParams(statusText, statusImage, statusData);
      }
      public void OnSendAcknowledgeState(object sender, MessagingOperationEventArgs e)
      {
      }
      public void OnUpdateChatMessageState(object sender, MessagingOperationEventArgs e)
      {
      }
      public void OnChatMessageUpdateReceived(object sender, MessagingOperationEventArgs e)
      {
      }
      public void OnSendInvitationReplyState(object sender, MessagingOperationEventArgs e)
      {
      }
      public void OnSaveMediaSessionState(object sender, SaveMediaSessionEventArgs e)
      {
      }
      public void OnNotifyPresenceState(object sender, NetworkOperationEventArgs e)
      {
      }
      public void OnMediaSessionUpdated(object sender, MediaSessionUpdateEventArgs e)
      {
      }
      public void OnCreateAccountState(object sender, NetworkOperationEventArgs e)
      {
      }
      public void OnRequestUserInfoState(object sender, NetworkOperationEventArgs e)
      {
         UpdatewWindowView();
      }
      public void OnSaveAccountDataState(object sender, SaveAccountDataEventArgs e)
      {
      }
      public void OnLoadAccountDataState(object sender, NetworkOperationEventArgs e)
      {
      }
      public void OnSyncContactsState(object sender, NetworkOperationEventArgs e)
      {
      }
      public void OnDropAccountState(object sender, NetworkOperationEventArgs e)
      {
      }
      public void OnSeekUsersState(object sender, NetworkOperationEventArgs e)
      {
      }
      public void OnLogonState(object sender, NetworkOperationEventArgs e)
      {
      }

      public void OnPresenceNotified(object sender, MessagingOperationEventArgs e)
      {
         SetStatusBarParams(null, null, null);
      }
      public void OnInvitationReceived(object sender, MessagingOperationEventArgs e)
      {
      }
      public void OnChatMessageReceived(object sender, MessagingOperationEventArgs e)
      {
         if (!IsVisible) return;

         if (e.EventMessage.Action == ServiceActions.TXTMSG)
         {
            if (IsActive)
            {
               FlashWindow(FlashType.None, 5, null); // see window_Flash handler
            }
            else
            {
               ActiveMediaSession = e.EventMessage.MediaSession;

               if (WindowState == FormWindowState.Minimized)
               {
                  FlashWindow(5);
               }
               else
               {
                  FlashWindow(FlashType.None, 5, null); // see window_Flash handler
               }
            }
            SetStatusBarParams(null, null, null);
         }
         else if (ActiveMediaSession == e.EventMessage.MediaSession &&
                  e.EventMessage.Action == ServiceActions.MSGTYPING)
         {
            TypingNotification tn = (TypingNotification)e.EventMessage;

            if (tn.Erased)
            {
               SetStatusBarParams(Resources.S_user_erased_message.Replace("<user>", e.EventMessage.Sender.CustomName), null, null);
            }
            else if (tn.Paused)
            {
               SetStatusBarParams(null, null, null);
            }
            else
            {
               SetStatusBarParams(Resources.S_user_is_typing_a_message.Replace("<user>", e.EventMessage.Sender.CustomName), null, null);
            }
            DelayedAction.Do(statusBar, () => SetStatusBarParams(null, null, null), 15000, true);
         }
      }
      public void OnAcknowledgeReceived(object sender, MessagingOperationEventArgs e)
      {
         string statusText = null;
         Image statusImage = null;

         if (e.Error != null)
         {
            statusText = e.Error.Reason;
            statusImage = FExclamationImage;
         }
         else
         {
            string users = e.RequestMessage.MediaSession.RecipientsNames;
            IEnumerable<User> failedUsers = (IEnumerable<User>)e.GetResult("FailedUsers", new User[] { });

            switch (e.RequestMessage.Action)
            {
               case ServiceActions.SESSIONREQ:
                  {
                     if (failedUsers.Count() > 0)
                     {
                        statusText = "These users were failed with invitation delivering: " + StringExt.Join(failedUsers.Select(user => user.ToString()), ", ");
                     }
                     else if (e.ReplyMessage.Result == 0)
                     {
                        statusText = "Last invitation was sent to the server at " + DateTime.Now.ToLongTimeString();
                     }
                     else if (e.ReplyMessage.Result == 1)
                     {
                        statusText = Resources.S_Last_invitation_was_delivered + users;
                     }
                     else
                     {
                        statusText = "Invitation delivering result for " + StringExt.Join(e.RequestMessage.Recipients, ", ") + " is unknown";
                     }
                     break;
                  }
               case ServiceActions.TXTMSG:
                  {
                     if (e.ReplyMessage.Result == 0)
                     {
                        statusText = "Last message to " + users + " was sent to the server at " + DateTime.Now.ToLongTimeString();
                     }
                     else
                     {
                        if (e.RequestMessage.MediaSession.IsPersonal)
                        {
                           switch (e.ReplyMessage.Result)
                           {
                              case 1:
                                 {
                                    statusText = Resources.S_Last_message_has_been_delivered.Replace("<user>", users).Replace("<time>", DateTime.Now.ToLongTimeString());
                                    break;
                                 }
                              case 2:
                                 {
                                    statusText = e.RequestMessage.Recipient.ToString() + " is offline now. Your message will be delivered as soon as the user will be online.";
                                    break;
                                 }
                              default:
                                 {
                                    statusText = "Message delivering result for " + e.RequestMessage.Recipient.ToString() + " is unknown";
                                    break;
                                 }
                           }
                        }
                        else
                        {
                           if (failedUsers.Count() > 0)
                           {
                              statusText = "These users were failed with message delivering: " + StringExt.Join(failedUsers.Select(user => user.ToString()), ", ");
                           }
                           else
                           {
                              statusText = "Last message was delivered to these users: " + StringExt.Join(e.RequestMessage.Recipients, ", ");
                           }
                        }
                     }
                     break;
                  }
            }
         }

         SetStatusBarParams(statusText, statusImage, e.Error);
      }
      public void OnInvitationReplyReceived(object sender, MessagingOperationEventArgs e)
      {
      }

      #endregion

      #region Event handlers

      private void menu_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.Menu);
      }
      private void window_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.Pattern);
      }
      private void menuMedia_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.AppMenu);
      }
      private void toolStrip_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.ToolStrip);
      }
      private void statusBar_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.StatusStrip);
         FCommunicator.DrawStatusBar(ColorTheme, sender as StatusStrip, e.Graphics);
      }
      private void sessionButton_Paint(object sender, PaintEventArgs e)
      {
         ToolStripButton button = (ToolStripButton)sender;
         MediaSession session = (MediaSession)button.Tag;
         Font font = button.Checked && RenderMode == ToolStripRenderMode.System && Computer.OSPlatform == OS.WindowsXP ? FButtonFontB : FButtonFont;
         Image image = session.Tag as Image ?? FSessionButtonImage;

         e.Graphics.DrawImageUnscaled(image, 4, (button.Height - image.Height) / 2);

         e.Graphics.DrawString(session.Caption, font, Brushes.Black,
                               new RectangleF(21, (button.Height - font.Height - 2) / 2, button.Width - 25, button.Height - 5), FButtonStringFormat);
      }
      private void toolStripItem_Paint(object sender, PaintEventArgs e)
      {
         ToolStripItem item = (ToolStripItem)sender;

         if (item == buttonSelectSession)
         {
            e.Graphics.DrawImageUnscaled(item.Selected || item.Pressed ? FDropDownArrowImage1 : FDropDownArrowImage2, 2, 9);
            e.Graphics.DrawImageUnscaled(item.Image, 12, (item.Height - item.Image.Height) / 2);
         }
         else if (Settings.Default.ShowMediaWindowMenuBarIcons && !Settings.Default.ShowMediaWindowMenuBarText)
         {
            if (item == menuItemSession)
            {
               e.Graphics.DrawImageUnscaled(FSessionMenuImage, 3, 0 + (item.Height - item.Image.Height) / 2);
               e.Graphics.DrawImageUnscaled(item.Selected || item.Pressed ? FDropDownArrowImage1 : FDropDownArrowImage2, 23, 9);
            }
            else if (item == menuItemHistory)
            {
               e.Graphics.DrawImageUnscaled(FHistoryMenuImage, 4, 1 + (item.Height - item.Image.Height) / 2);
               e.Graphics.DrawImageUnscaled(item.Selected || item.Pressed ? FDropDownArrowImage1 : FDropDownArrowImage2, 23, 9);
            }
            else if (item == menuItemFind)
            {
               e.Graphics.DrawImageUnscaled(FFindMenuImage, 4, 1 + (item.Height - item.Image.Height) / 2);
               e.Graphics.DrawImageUnscaled(item.Selected || item.Pressed ? FDropDownArrowImage1 : FDropDownArrowImage2, 23, 9);
            }
            else if (item == menuItemContact)
            {
               e.Graphics.DrawImageUnscaled(FContactMenuImage, 3, 0 + (item.Height - item.Image.Height) / 2);
               e.Graphics.DrawImageUnscaled(item.Selected || item.Pressed ? FDropDownArrowImage1 : FDropDownArrowImage2, 23, 9);
            }
         }
      }
      private void panelSplitter_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.Pattern);
         e.Graphics.DrawImageUnscaled(FSplitterImage, e.ClipRectangle.Width / 2 - 5, 0);
         e.Graphics.DrawLine(Pens.DarkGray, 0, e.ClipRectangle.Height - 1, e.ClipRectangle.Width, e.ClipRectangle.Height - 1);
      }

      private void window_Load(object sender, EventArgs e)
      {
         if (Settings.Default.MediaWindowRect.Size.Width > MinimumSize.Width &&
             Settings.Default.MediaWindowRect.Size.Height > MinimumSize.Height)
         {
            Size = Settings.Default.MediaWindowRect.Size;
         }
         else
         {
            Size = FDefaultSize;
         }
         if (ExclusiveSessionMode == false &&
             Settings.Default.MediaWindowRect.Location.X > 0 &&
             Settings.Default.MediaWindowRect.Location.Y > 0)
         {
            Location = Settings.Default.MediaWindowRect.Location;
         }
         else
         {
            CenterToScreen();
         }

         toolStrip_EnabledChanged(menuMedia, null);
         toolStrip_EnabledChanged(toolStripBottom, null);

         if (Settings.Default.InputHeight > 20) panelInputLayout.Height = Settings.Default.InputHeight;

         AdjustControlsGeometry();
      }
      private void window_KeyDown(object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.Escape)
         {
            if (textBoxInput.Text != "")
            {
               textBoxInput.Text = "";
            }
            else if (TextSearchVisible)
            {
               HideTextSearch();
            }
            else
            {
               Hide();
            }
         }
         else if (e.Control && e.Shift && e.KeyCode == Keys.Tab)
         {
            int index = FMediaSessions.IndexOf(ActiveMediaSession);

            if (index >= 0)
            {
               if (++index == FMediaSessions.Count) index = 0;
               ActiveMediaSession = FMediaSessions[index];
               e.SuppressKeyPress = true;
            }
         }
         else if (e.Control && e.KeyCode == Keys.Tab)
         {
            int index = FMediaSessions.IndexOf(ActiveMediaSession);

            if (index >= 0)
            {
               if (--index < 0) index = FMediaSessions.Count - 1;
               ActiveMediaSession = FMediaSessions[index];
               e.SuppressKeyPress = true;
            }
         }
         else if (textBoxInput.Focused)
         {
            if (e.KeyCode == Keys.Enter)
            {
               if (string.IsNullOrEmpty(Settings.Default.SendOn))
               {
                  Settings.Default.SendOn = e.Control ? "Ctrl+Enter" : "Enter";
               }
               if (Settings.Default.SendOn == "Enter" && !e.Control ||
                   Settings.Default.SendOn == "Ctrl+Enter" && e.Control ||
                   e.KeyCode == Keys.S && e.Alt)
               {
                  e.SuppressKeyPress = true;

                  DoPost();
               }
            }
            else if (e.Control && e.KeyCode == Keys.A)
            {
               textBoxInput.SelectAll();
            }
         }
      }
      private void window_ResizeEnd(object sender, EventArgs e)
      {
         // Resize event occure when moving window too, so prevent refreshing in this case
         if (Settings.Default.MediaWindowRect.Width != Bounds.Width ||
             Settings.Default.MediaWindowRect.Height != Bounds.Height)
         {
            Settings.Default.MediaWindowRect = Bounds;
            AdjustControlsGeometry();
         }
      }
      private void window_VisibleChanged(object sender, EventArgs e)
      {
         if (Visible) BeginInvoke(new Action(() => PrepareWindowForChat()));
      }
      private void window_LocationChanged(object sender, EventArgs e)
      {
         // When window has been minimized Bounds property is obscure, and this cause the program to interpret it wrong.
         if (WindowState == FormWindowState.Normal) Settings.Default.MediaWindowRect = Bounds;
      }
      private void window_WindowStateChanged(object sender, EventArgs e)
      {
         if (WindowState == FormWindowState.Normal || WindowState == FormWindowState.Maximized)
         {
            DelayedAction.Do(() => { PrepareWindowForChat(); }, 200);
         }
      }
      private void window_WindowsThemeChanged(object sender, EventArgs e)
      {
         AdjustControlsGeometry();
      }
      private void window_SystemMenu(object sender, CancelEventArgs e)
      {
         e.Cancel = true;
         Point p = PointToScreen(ClientRectangle.Location);
         FCommunicator.Components.menuChatSession.Tag = ActiveChatSession;
         MenuWrapper.ShowMenu(FCommunicator.Components.menuChatSession, p.X, p.Y);
      }
      private void window_Activation(object sender, ActivationEventArgs e)
      {
         FCommunicator._ActiveMediaWindow = this;

         buttonEmoticons.DropDown = FCommunicator.Components.menuEmoticons;

         if (ActiveMediaSession != null) ActiveMediaSession.FireActivatedEvent();
      }
      private void window_Flash(object sender, FlashWindowEventArgs e)
      {
         if (IsActive)
         {
            foreach (ServiceMessage message in FCommunicator.UnacceptedMessages.Where(m => m.MediaSession != ActiveMediaSession))
            {
               if (message.MediaSession != null) message.MediaSession.Tag = (e.RemainTimes == 0 ? FSessionButtonImageFlashed : (e.Active ? FSessionButtonImageFlashed : FSessionButtonImage));
            }
            toolStripMiddle.Refresh();
         }
      }
      private void window_SessionSelect(IMediaSession session, bool selected, bool exclusive)
      {
         if (exclusive) DeselectAllSessionButtons();

         ToolStripButton button = GetSessionSelectButton(session);

         if (button != null)
         {
            if (!button.Visible && exclusive && selected) toolStripMiddle.Items.Insert(0, button);

            button.Visible = selected;
            button.Checked = selected;
            FHiddenSessions.Remove(session);
            ArrangeSessionButtons();
         }
         ToolStripMenuItem item = GetSessionSelectItem(session);
         if (item != null) item.Checked = selected;

         UpdatewWindowView();

         textBoxInput.Focus();

         if (TextSearchVisible && session is ChatSession)
         {
            FLogToolbar["btnThisPage"].Text = ((session as ChatSession).ChatControl.HistoryPageIndex + 1).ToString();
         }
      }
      private void buttonSend_Click(object sender, EventArgs e)
      {
         DoPost();
      }
      private void textBoxInput_TextChanged(object sender, EventArgs e)
      {
         FInputCaretPos = textBoxInput.SelectionStart;
         SetStatusBarText(Resources.S_Characters_count + textBoxInput.Text.Length);
         textBoxInput.ScrollBars = textBoxInput.Lines.Length > 2 ? ScrollBars.Vertical : ScrollBars.None;
      }
      private void itemSelectSession_MouseDown(object sender, MouseEventArgs e)
      {
         ToolStripMenuItem item = (ToolStripMenuItem)sender;
         IMediaSession session = (IMediaSession)item.Tag;

         if (!item.Checked || FHiddenSessions.Contains(session)) SelectSession(session); else if (MulticastMode) DeselectSession(session);
      }
      private void itemMulticastMode_Click(object sender, EventArgs e)
      {
         MulticastMode = itemMulticastMode.Tag == null;

         if (MulticastMode)
         {
            itemMulticastMode.Tag = ActiveMediaSession == null ? null : ActiveMediaSession.Gsid;
            SelectAllSessions();
         }
         else
         {
            DeselectAllSessions();
            ActiveMediaSession = FMediaSessions.GetItemById(itemMulticastMode.Tag.ToString());
            itemMulticastMode.Tag = null;
         }
      }
      private void textBoxInput_MouseEnter(object sender, EventArgs e)
      {
         if (IsAppActive && IsActive) textBoxInput.Focus();
      }
      private void textBoxInput_Enter(object sender, EventArgs e)
      {
         textBoxInput.SelectionStart = FInputCaretPos;
         textBoxInput.SelectionLength = 0;
      }
      private void textBoxInput_Click(object sender, EventArgs e)
      {
         FInputCaretPos = textBoxInput.SelectionStart;
      }
      private void textBoxInput_KeyUp(object sender, KeyEventArgs e)
      {
         FInputCaretPos = textBoxInput.SelectionStart;
      }
      private void buttonSelectSession_MouseDown(object sender, MouseEventArgs e)
      {
         ToolStripButton button = (ToolStripButton)sender;
         IMediaSession session = (IMediaSession)button.Tag;

         if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right)
         {
            if (MulticastMode && button.Checked)
            {
               DeselectSession(session);
            }
            else
            {
               SelectSession(session);
            }
            if (e.Button == MouseButtons.Right)
            {
               if (FLastShownMenu == null)
               {
                  FLastShownMenu = InternetCommunicator.Self.Components.menuContact;
                  InternetCommunicator.Self.ShowUserMenu(ActiveChatSession.Interlocutor);
               }
               else if (FLastShownMenu == InternetCommunicator.Self.Components.menuContact)
               {
                  FLastShownMenu = null;
                  InternetCommunicator.Self.ShowSessionMenu(ActiveChatSession);
               }
            }
         }
      }
      private void buttonSelectSession_LocationChanged(object sender, EventArgs e)
      {
         ToolStripButton button = (ToolStripButton)sender;
         IMediaSession session = (IMediaSession)button.Tag;
         int index = toolStripMiddle.Items.IndexOf(button);
         ToolStripMenuItem item = GetSessionSelectItem(session);
         if (item == null)
         {
            item = new ToolStripMenuItem();
            item.Tag = session;
            item.AutoSize = true;
            item.MouseDown += new MouseEventHandler(itemSelectSession_MouseDown);
            item.Checked = button.Checked;
            item.Text = session.Caption;
         }
         menuSelectSession.Items.Insert(index, item);
      }
      private void statusBarLabel_MouseDown(object sender, MouseEventArgs e)
      {
         if (e.Button == MouseButtons.Left)
         {
            if (statusBarLabel.Tag != null)
            {
               Exception error = (Exception)statusBarLabel.Tag;

               SetStatusBarParams(null, null, null);

               FCommunicator.ShowError("", error);
            }
            else if (ActiveChatSession != null)
            {
               Collection<string> links = Utils.ExtractLinks(ActiveChatSession.Interlocutor.Status.Message);
               if (links.Count > 0) Shell.OpenLink(links[0]);
            }
         }
      }
      private void buttonClearText_Click(object sender, EventArgs e)
      {
         textBoxInput.Text = "";
      }
      private void session_Closed(object sender, EventArgs e)
      {
         DetachSession(sender as IMediaSession);
      }
      private void session_Activated(object sender, EventArgs e)
      {
         ChatSession session = sender as ChatSession;

         UpdatewWindowView();

         if (session != null && IsActive)
         {
            ServiceMessage message = FCommunicator.UnacceptedMessages.FirstOrDefault(m => m.MediaSession == session);

            if (message != null) FCommunicator.AcceptMessage(message);
         }
      }
      private void session_Closing(object sender, CancelEventArgs e)
      {
         if (sender == FMulticastSession) e.Cancel = true;
      }
      private void session_ParticipantsChanged(object sender, ParticipantsChangedEventArgs e)
      {
         //
      }
      private void chatControl_HistoryPageChanged(object sender, EventArgs e)
      {
         ChatControl chatControl = sender as ChatControl;

         if (FLogToolbar != null) FLogToolbar["btnThisPage"].Text = (chatControl.HistoryPageIndex + 1).ToString();

         if (!TextSearchVisible && chatControl.HistoryFilesCount == chatControl.HistoryPageIndex + 1) textBoxInput.Focus();
      }
      private void buttonSelectSession_DoubleClick(object sender, EventArgs e)
      {
         if (Settings.Default.HideSessionOnDClick) HideSession((sender as ToolStripButton).Tag as IMediaSession);
      }
      private void itemCloseSession_Click(object sender, EventArgs e)
      {
         if (ActiveMediaSession != null) ActiveMediaSession.Close();
      }
      private void menu_Opening(object sender, CancelEventArgs e)
      {
         if (sender == menuView)
         {
            itemShowMenuBar.Checked = Settings.Default.ShowMediaWindowMenuBar;
            itemShowMenuBarText.Checked = Settings.Default.ShowMediaWindowMenuBarText;
            itemShowMenuBarIcons.Checked = Settings.Default.ShowMediaWindowMenuBarIcons;
            itemShowSplitter.Checked = Settings.Default.ShowInputResizeBar;
            itemShowTopToolbar.Checked = Settings.Default.ShowMediaWindowTopToolbar;
            itemShowBottomToolbar.Checked = Settings.Default.ShowMediaWindowBottomToolbar;
         }
         MenuWrapper.MakeFadeEffect((ContextMenuStrip)sender, FCommunicator.MaxMenuOpacity);
      }
      private void emoticonMenu_EmoSelected(object sender, EventArgs e)
      {
         if (IsActive && FCommunicator.EmoticonPopup.SelectedEmo != null) InsertEmo(FCommunicator.EmoticonPopup.SelectedEmo.DefaultNotation);
      }
      private void labelCloseSession_MouseEnter(object sender, EventArgs e)
      {
         (sender as ToolStripLabel).Image = Resources.CloseChromeGrayDark12;
      }
      private void labelCloseSession_MouseLeave(object sender, EventArgs e)
      {
         (sender as ToolStripLabel).Image = Resources.CloseChromeGrayLight12;
      }
      private void labelCloseSession_MouseDown(object sender, MouseEventArgs e)
      {
         (sender as ToolStripLabel).Image = Resources.CloseChromeGrayMiddle12;
      }
      private void labelCloseSession_Click(object sender, EventArgs e)
      {
         (sender as ToolStripLabel).Image = Resources.CloseChromeGrayLight12;
         if (ActiveMediaSession != null) ActiveMediaSession.Close();
      }
      private void statusBarLabelCloseSession_MouseLeave(object sender, EventArgs e)
      {
         if (statusBarLabel.Tag == null) statusBarLabelCloseSession.Image = statusBarLabel.Image;
      }
      private void toolStrip_EnabledChanged(object sender, EventArgs e)
      {
         ToolStrip ts = sender as ToolStrip;

         ControlEffects.Slide(ts.Parent, ts.Enabled ? SlideAction.Expand : SlideAction.Collapse, false, e != null,
                  (action) => panelSessionVisualizer.SuspendLayout(),
                  (action) =>
                  {
                     AdjustControlsGeometry();
                     panelSessionVisualizer.ResumeLayout(true);
                  });
      }
      private void toolStrip_MouseUp(object sender, MouseEventArgs e)
      {
         if (e.Button == MouseButtons.Right) MenuWrapper.ShowMenu(menuView);
      }
      private void itemShowToolBar_Click(object sender, EventArgs e)
      {
         if (sender == itemShowSplitter)
         {
            Settings.Default.ShowInputResizeBar = !Settings.Default.ShowInputResizeBar;
         }
         else if (sender == itemShowMenuBar)
         {
            Settings.Default.ShowMediaWindowMenuBar = !Settings.Default.ShowMediaWindowMenuBar;
         }
         else if (sender == itemShowTopToolbar)
         {
            // Leave this line *before* property inverting because of show/hide toolbar side effects
            if (!Settings.Default.ShowMediaWindowTopToolbar) Settings.Default.ShowMediaWindowMenuBarIcons = false;

            Settings.Default.ShowMediaWindowTopToolbar = !Settings.Default.ShowMediaWindowTopToolbar;
         }
         else if (sender == itemShowMenuBarText)
         {
            Settings.Default.ShowMediaWindowMenuBarText = Settings.Default.ShowMediaWindowMenuBarIcons ?
                                                         !Settings.Default.ShowMediaWindowMenuBarText : true;
         }
         else if (sender == itemShowMenuBarIcons)
         {
            Settings.Default.ShowMediaWindowMenuBarIcons = !Settings.Default.ShowMediaWindowTopToolbar ?
                                                           !Settings.Default.ShowMediaWindowMenuBarIcons : false;
         }
         else if (sender == itemShowBottomToolbar)
         {
            Settings.Default.ShowMediaWindowBottomToolbar = !Settings.Default.ShowMediaWindowBottomToolbar;
         }
      }
      private void communicator_MessageAccepted(object sender, MessageAcceptedEventArgs e)
      {
         StopFlash();

         if (e.Message.MediaSession != null) e.Message.MediaSession.Tag = FSessionButtonImage;

         toolStripMiddle.Refresh();
      }
      private void communicator_CurrentAccountChanged(object sender, PropertyChangedEventArgs e)
      {
         if (FMulticastSession != null) FMulticastSession.Account = FCommunicator.CurrentAccount;
      }
      private void communicator_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
         if (e.PropertyName == "ColorTheme") ColorTheme = FCommunicator.ColorTheme;
         else if (e.PropertyName == "RenderMode") RenderMode = FCommunicator.RenderMode;
         else if (e.PropertyName == "Culture") Translate(FCommunicator.Culture);
      }
      private void settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
         if (e.PropertyName == "ShowInputResizeBar")
         {
            panelSplitter.Visible = Settings.Default.ShowInputResizeBar;
            panelSessionVisualizer.ResumeLayout();
            panelSessionVisualizerBase.ResumeLayout();
         }
         else if (e.PropertyName == "InputFontSize")
         {
            textBoxInput.Font = new Font(Settings.Default.InputFont, Settings.Default.InputFontSize);
         }
         else if (e.PropertyName == "ShowMediaWindowMenuBar")
         {
            menuMedia.Items.Add(labelCloseSession);
         }
         else if (e.PropertyName == "ShowMediaWindowMenuBarIcons" || e.PropertyName == "ShowMediaWindowMenuBarText")
         {
            AdjustToolbarButtons();
         }
      }

      private void logToolbar_HtmlControlEvent(object sender, HtmlControlEventArgs e)
      {
         if (e.Target.Id == "inputFind")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_EDIT_VALUE_CHANGED)
            {
               e.Handled = true;

               if (e.Target.Text.Length != 1)
               {
                  DelayedAction.Do(sender, () =>
                  {
                     ActiveChatSession.ChatControl.FindText(e.Target.Text, true);
                  },
                  600, true);
               }
            }
         }
         else if (e.Target.Id == "btnNext")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_CLICK)
            {
               e.Handled = true;
               ActiveChatSession.ChatControl.FindText(SearchString, true);
            }
         }
         else if (e.Target.Id == "btnPrev")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_CLICK)
            {
               e.Handled = true;
               ActiveChatSession.ChatControl.FindText(SearchString, false);
            }
         }
         else if (e.Target.Id == "btnNextPage")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_CLICK)
            {
               e.Handled = true;
               ActiveChatSession.ChatControl.NextHistoryPage();
            }
         }
         else if (e.Target.Id == "btnThisPage")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_CLICK)
            {
               e.Handled = true;
               MenuWrapper.ShowMenu(FCommunicator.Components.menuHistoryPages);
            }
         }
         else if (e.Target.Id == "btnPrevPage")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_CLICK)
            {
               e.Handled = true;
               ActiveChatSession.ChatControl.PrevHistoryPage();
            }
         }
         else if (e.Target.Id == "btnClose")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_CLICK)
            {
               e.Handled = true;
               HideTextSearch();
            }
         }
         else if (e.Target.Id == "cbSearchString")
         {
            if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_STATE_CHANGED)
            {
               e.Handled = true;
            }
         }
      }
      private void logToolbar_HtmlControlKeyPress(object sender, HtmlKeyEventArgs e)
      {
         if (e.Target.Id == "inputFind")
         {
            if (e.Key == Keys.Enter)
            {
               e.Handled = true;

               // This event generated by HTMLayout multiple times, so leave the last one:
               DelayedAction.Do(sender, () =>
               {
                  if (e.Shift) ActiveChatSession.ChatControl.FindText(e.Target.Text, false);
                  else ActiveChatSession.ChatControl.FindText(e.Target.Text, true);
               },
               10, true);
            }
         }
      }

      #endregion
   }
}